package com.hiof.moraa.server.dao;

import com.hiof.moraa.mapping.TblAthlete;
import com.hiof.moraa.mapping.TblAthleteLiveMedia;
import com.hiof.moraa.server.service.model.LiveMediaFeed;
import com.hiof.moraa.server.service.model.TypeOfAttendant;
import com.hiof.moraa.util.FileUtils;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Bergy
 */
public class HibernateAthleteLiveMediaDAOImp implements AthleteLiveMediaDAO {

    private SessionFactory factory;

    public SessionFactory getFactory() {
        return factory;
    }

    public void setFactory(SessionFactory factory) {
        this.factory = factory;
    }

    @Override
    public LiveMediaFeed insertAthleteLiveMediaFeed(int athleteId, String filePath, double lat, double lng, double height, Timestamp timestamp) {
        TblAthleteLiveMedia athleteLiveMedia = new TblAthleteLiveMedia();
        try {
            TblAthlete athlete = (TblAthlete) factory.getCurrentSession().get(TblAthlete.class, athleteId);
            athleteLiveMedia.setTblAthlete(athlete);
            athleteLiveMedia.setMediaType(FileUtils.computeMediaType(filePath));
            athleteLiveMedia.setMediaPath(filePath);
            athleteLiveMedia.setHeight(height);
            athleteLiveMedia.setLat(lat);
            athleteLiveMedia.setLng(lng);
            athleteLiveMedia.setTimeStamp(timestamp);
            factory.getCurrentSession().save(athleteLiveMedia);

        } catch (HibernateException e) {
            Logger.getLogger(HibernateAthleteLiveMediaDAOImp.class.getName()).log(Level.SEVERE, "Hibernate Exception Occured", e);
            throw e;
        }

        LiveMediaFeed liveMediaFeed = convert2LiveMediaFeed(athleteLiveMedia);
        return liveMediaFeed;
    }

    @Override
    public List<LiveMediaFeed> getAllMediaFeedByAthleteId(int athleteId) {
        Session session = factory.getCurrentSession();

        String hql = "from TblAthleteLiveMedia media where media.tblAthlete.id = :athleteId order by media.timeStamp desc";
        Query query = session.createQuery(hql);
        query.setInteger("athleteId", athleteId);
        List<TblAthleteLiveMedia> athleteLiveMedias = query.list();

        List<LiveMediaFeed> result = fetchToLiveMediaFeedList(athleteLiveMedias);
        athleteLiveMedias.clear();
        return result;
    }

    @Override
    public List<LiveMediaFeed> getLatestLiveMediaFeedOfAllAthletesInOneRoute(int routeId, int numOfFeed) {
        Session session = factory.getCurrentSession();

        String hql = "from TblAthleteLiveMedia media where media.tblAthlete.tblRoute.id = :routeId "
                + "order by media.timeStamp desc";
        Query query = session.createQuery(hql);
        query.setInteger("routeId", routeId);
        query.setMaxResults(numOfFeed);
        List<TblAthleteLiveMedia> athleteLiveMedias = query.list();

        List<LiveMediaFeed> result = fetchToLiveMediaFeedList(athleteLiveMedias);
        athleteLiveMedias.clear();
        return result;
    }

    @Override
    public List<LiveMediaFeed> getLatestLiveMediaFeedOfOneAthleteInOneRoute(String username, int routeId, int numOfLiveMediaFeed) {
        Session session = factory.getCurrentSession();

        String hql = "from TblAthleteLiveMedia media where media.tblAthlete.tblUser.username = :username and media.tblAthlete.tblRoute.id = :routeId "
                + "order by media.timeStamp desc";
        Query query = session.createQuery(hql);
        query.setString("username", username);
        query.setInteger("routeId", routeId);
        query.setMaxResults(numOfLiveMediaFeed);
        List<TblAthleteLiveMedia> athleteLiveMedias = query.list();

        List<LiveMediaFeed> result = fetchToLiveMediaFeedList(athleteLiveMedias);
        athleteLiveMedias.clear();
        return result;
    }

    private List<LiveMediaFeed> fetchToLiveMediaFeedList(List<TblAthleteLiveMedia> athleteLiveMedias) {
        List<LiveMediaFeed> result = new ArrayList<LiveMediaFeed>();
        for (TblAthleteLiveMedia media : athleteLiveMedias) {
            result.add(convert2LiveMediaFeed(media));
        }
        return result;
    }

    private LiveMediaFeed convert2LiveMediaFeed(TblAthleteLiveMedia athleteLiveMedia) {
        if (athleteLiveMedia == null)
            return null;
        LiveMediaFeed liveMediaFeed = new LiveMediaFeed(
                athleteLiveMedia.getTblAthlete().getTblUser().getId(),
                athleteLiveMedia.getTblAthlete().getTblUser().getUsername(),
                athleteLiveMedia.getTblAthlete().getTblUser().getFirstName() + " " + athleteLiveMedia.getTblAthlete().getTblUser().getLastName(),
                athleteLiveMedia.getTblAthlete().getTblUser().getProfilePicture(),
                athleteLiveMedia.getTimeStamp(),
                athleteLiveMedia.getTblAthlete().getAttendantCode(),
                athleteLiveMedia.getMediaPath(), athleteLiveMedia.getLat(),
                athleteLiveMedia.getLng(), athleteLiveMedia.getHeight(), TypeOfAttendant.ATHLETE);
        return liveMediaFeed;
    }
}
